// 引入对象类
import Snake from "./Snake";
import Food from "./Food";
import ScorePanel from "./ScorePanel";

// 定义控制方法的类
class GameControl {
  // 定义三个属性
  // 蛇
  snake: Snake;
  // 食物
  food: Food;
  // 记分牌
  scorePanel: ScorePanel;

  // 存储蛇的移动方向
  direction: String = '';
  // 记录游戏是否结束
  isLive: boolean = true;

  constructor () {
    this.snake = new Snake();
    this.food = new Food();
    this.scorePanel = new ScorePanel();

    this.init();
  }

  // 游戏初始化
  init () {
    // 绑定键盘按键按下的事情
    // 第一个this 指向了document
    // 第二个this bind将this修改了指向,指向了谁调用了这个keydownHandle()方法.
    document.addEventListener('keydown', this.keydownHandle.bind(this));
    // 调用run方法
    this.run();
  }

  // 创建键盘按下的响应函数
  keydownHandle(event: KeyboardEvent) {
    console.log(event.key);
    if (event.key) return this.direction = event.key;
  }
  
  // 控制 蛇的移动 的方法
  run () {
    // 根据方向(this.direction) 来使蛇的位置改变
    // 向上 top 减少
    // 向下 top 增加
    // 向左 left 减少
    // 向右 left 增加
    // 获取蛇现在坐标
    let X = this.snake.X;
    let Y = this.snake.Y;

    // 根据方向修改X值和Y值
    switch (this.direction) {
      // 向上
      case "ArrowUp":
      case "Up":
        Y -= 10;
        break;
      // 向下
      case "ArrowDown":
      case "Down":
        Y += 10;
        break;
      // 向左
      case "ArrowLeft":
      case "Left":
        X -= 10;
        break;
      // 向右
      case "ArrowRight":
      case "Right":
        X += 10;
        break;
      // 其他按键
      default:
        break;
    }

    // 检查蛇是否吃到了食物
    this.checkEat(X, Y)

    // 修改蛇的位置
    try {
      this.snake.X = X;
      this.snake.Y = Y;
    } catch (e: any) {
      // 进入异常.游戏结束
      alert(e.message + 'GAME OVER');
      this.isLive = false;
    }
    

    // 定时器
    // 随等级提高,减短定时器触发时间
    this.isLive && setTimeout(this.run.bind(this), 300 - (this.scorePanel.level - 1) * 30);

  }

  // 检查蛇是否吃到食物
  checkEat(X: number, Y:number) {
    if (X === this.food.X && Y === this.food.Y) {
      this.food.change()
      this.snake.addBody()
      this.scorePanel.addScore()
    }
  }
}

export default GameControl;